﻿/**
 * Copyright (C) 2011 original author and authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NGuice.Inject.Spi;
using NGuice.Inject.Internal.Util;
using System.Reflection;
using System.Collections;
using System.Globalization;
using System.IO;

namespace NGuice.Inject.Internal
{
    /// <summary>
    /// 错误消息的集合。如果此类型作为方法参数传递，仅仅当心错误不加入到此集合中方法才被认为是成功运行的。
    /// 错误集能够链接以便提供额外的上下文。添加上下文，可以调用WithSource以创建新的错误集实例。所有添加
    /// 到返回的实例中的消息都将包含完整的上下文。为了避免冗余的上下文，WithSource应该尽量少调用
    /// </summary>
    [Serializable]
    public sealed class Errors
    {
        /// <summary>
        /// 根错误对象，用于访问错误列表
        /// </summary>
        private readonly Errors root;

        /// <summary>
        /// 父错误对象，用于访问源对象链
        /// </summary>
        private readonly Errors parent;

        /// <summary>
        /// 添加到错误集的叶子源
        /// </summary>
        private readonly object source;

        /// <summary>
        /// 错误消息列表，如果本错误集为根错误集则为null
        /// </summary>
        private List<Message> errors;

        public Errors()
        {
            this.root = this;
            this.parent = null;
            this.source = SourceProvider.UNKNOWN_SOURCE;
        }

        public Errors(object source)
        {
            this.root = this;
            this.parent = null;
            this.source = source;
        }

        private Errors(Errors parent, object source)
        {
            this.root = parent.root;
            this.parent = parent;
            this.source = source;
        }

        public Errors WithSource(object source)
        {
            return source == SourceProvider.UNKNOWN_SOURCE ? this : new Errors(this, source);
        }

        public Errors MissingImplementation<T>(Key<T> key)
        {
            return AddMessage("No implementation for {0} was bound.", key);
        }

        public Errors JITDisabled<T>(Key<T> key)
        {
            return AddMessage("Explicit bindings are required and {0} is not explicitly bound.", key);
        }

        public Errors JITDisabled(Key key)
        {
            return AddMessage("Explicit bindings are required and {0} is not explicitly bound.", key);
        }

        public Errors ConverterReturnedNull(string stringValue, object source, Type type, TypeConverterBinding typeConverterBinding)
        {
            return AddMessage("Received null converting '{0}' (bound at {1}) to {2}\r\n" + " using {4}.", stringValue, Convert(source), type, typeConverterBinding);
        }

        public Errors ConversionTypeError(string stringValue, object source, Type type, TypeConverterBinding typeConverterBinding, object converted)
        {
            return AddMessage("Type mismatch converting '{0}' (bound at {1}) to {2}\r\n"
                + " using {3}.\r\n"
                + " Converter returned {4}.",
                stringValue, Convert(source), type, typeConverterBinding, converted);
        }

        public Errors ConversionError(string stringValue, object source, Type type, TypeConverterBinding typeConverterBinding, Exception cause)
        {
            return ErrorInUserCode(cause, "Error converting '{0}' (bound at{1}) to {2}\r\n"
                + " using {3}.\r\n"
                + " Reason: {4}",
                stringValue, Convert(source), type, typeConverterBinding, cause);
        }

        public Errors AmbiguousTypeConversion(string stringValue, object source, Type type, TypeConverterBinding a, TypeConverterBinding b)
        {
            return AddMessage("Multiple converters can convert '{0}' (bound at {1}) to {2}:\r\n"
                + " {3} and \r\n"
                + " {4}.\r\n"
                + " Please adjust your type converter configuration to avoid overlapping matches.",
                stringValue, Convert(source), type, a, b);
        }

        public Errors BindingToProvider()
        {
            return AddMessage("Binding to Provider is not allowed.");
        }

        public Errors SubtypeNotProvided(Type providerType, Type type)
        {
            return AddMessage("{0} doesn't provide instances of {1}.", providerType, type);
        }

        public Errors NotASubtype(Type implementationType, Type type)
        {
            return AddMessage("{0} doesn't extend {1}.", implementationType, type);
        }

        public Errors RecursiveImplementationType()
        {
            return AddMessage("[ImplementedBy] points to the same class it annotates.");
        }

        public Errors RecursiveProviderType()
        {
            return AddMessage("[ProvidedBy] points to the same class it annotates.");
        }

        public Errors MissingScopeAnnotation()
        {
            return AddMessage("Please annotate with [ScopeAnnotation]");
        }

        public Errors OptionalConstructor(ConstructorInfo constructor)
        {
            return AddMessage("%s is annotated [Inject(optional=true)] "
                + "but constructors cannot be optional.", constructor);
        }

        public Errors CannotBindToGuiceType(string simpleName)
        {
            return AddMessage("Binding to core guice framework type is not allowed: {0}.", simpleName);
        }

        public Errors ScopeNotFound(Type scopeAnnotation)
        {
            return AddMessage("No scope is bound to {0}.", scopeAnnotation);
        }

        public Errors ScopeAnnotationOnAbstractType(Type scopeAnnotation, Type type, object source)
        {
            return AddMessage("{0} is annotated with {1}, but scope annotations are not supported "
                + "for abstract types.\r\n Bound at {2}.", type, scopeAnnotation, Convert(source));
        }

        public Errors MisplacedBindingAnnotation(MemberInfo member, Attribute bindingAnnotation)
        {
            return AddMessage("{0} is annotated with {1}, but binding annotations should be applied "
                + "to its parameters instead.", member, bindingAnnotation);
        }

        private const string CONSTRUCTOR_RULES = "Classes must have either one (and only one) constructor annotated with [Inject] or a zero-argument constructor that is not private.";

        public Errors MissingConstructor(Type implementation)
        {
            return AddMessage("Could not find a suitable constructor in {0}. " + CONSTRUCTOR_RULES, implementation);
        }

        public Errors TooManyConstructors(Type implementation)
        {
            return AddMessage("{0} has more than one constructor annotated with [Inject] " + CONSTRUCTOR_RULES, implementation);
        }

        public Errors ConstructorNotDefinedByType(ConstructorInfo constructor, Type type)
        {
            return AddMessage("{0} does not define {1}", type, constructor);
        }

        public Errors DuplicateScopes(IScope existing, Type annotationType, IScope scope)
        {
            return AddMessage("Scope {0} is already bound to {1}. Cannot bind {2].", existing, annotationType, scope);
        }

        public Errors VoidProviderMethod()
        {
            return AddMessage("Provider methods must return a value. Do not return void.");
        }

        public Errors MissingConstantValues()
        {
            return AddMessage("Missing constant value. Please call to(...).");
        }

        public Errors CannotInjectInnerClass(Type type)
        {
            return AddMessage("Injecting into inner classes is not supported.  " + "Please use a 'static' class (top-level or nested) instead of {0}.", type);
        }

        public Errors DuplicateBindingAnnotations(MemberInfo member, Type a, Type b)
        {
            return AddMessage("{0} has more than one annotation annotated with [BindingAnnotation]: " + "{1} and {2}", member, a, b);
        }

        public Errors CannotInjectFinalField(FieldInfo field)
        {
            return AddMessage("Injected field {0} cannot be final.", field);
        }

        public Errors CannotInjectAbstractMethod(MethodInfo method)
        {
            return AddMessage("Injected method {0} cannot be abstract.", method);
        }

        public Errors CannotInjectNonVoidMethod(MethodInfo method)
        {
            return AddMessage("Injected method {0} must return void.", method);
        }

        public Errors CannotInjectMethodWithTypeParameters(MethodInfo method)
        {
            return AddMessage("Injected method {0} cannot declare type parameters of its own.", method);
        }

        public Errors DuplicateScopeAnnotations(Type a, Type b)
        {
            return AddMessage("More than one scope annotation was found: {0} and {1}.", a, b);
        }

        public Errors RecursiveBinding()
        {
            return AddMessage("Binding points to itself.");
        }

        public Errors BindingAlreadySet<T>(Key<T> key, object source)
        {
            return AddMessage("A binding to {0} was already configured at {1}.", key, Convert(source));
        }

        public Errors ChildBindingAlreadySet<T>(Key<T> key)
        {
            return AddMessage("A binding to {0} already exists on a child injector.", key);
        }

        public Errors ErrorCheckingDuplicateBinding<T>(Key<T> key, object source, Exception t)
        {
            return AddMessage(
                "A binding to {0} was already configured at {1} and an error was thrown "
              + "while checking duplicate bindings.  Error: {2}",
                key, source, t);
        }

        public Errors ErrorInjectingMethod(Exception cause)
        {
            return ErrorInUserCode(cause, "Error injecting method, {0}", cause);
        }

        public Errors ErrorNotifyingTypeListener(TypeListenerBinding listener, Type type, Exception cause)
        {
            return ErrorInUserCode(cause,
                "Error notifying TypeListener {0} (bound at {1}) of {2}.\r\n"
                + " Reason: {3}",
                listener.Listener, Convert(listener.Source), type, cause);
        }

        public Errors ErrorInjectingConstructor(Exception cause)
        {
            return ErrorInUserCode(cause, "Error injecting constructor, {0}", cause);
        }

        public Errors ErrorInProvider(Exception runtimeException)
        {
            Exception unwrapped = Unwrap(runtimeException);
            return ErrorInUserCode(unwrapped, "Error in custom provider, {0}", unwrapped);
        }

        public Errors ErrorInUserInjector<T>(IMembersInjector<T> listener, Type type, Exception cause)
        {
            return ErrorInUserCode(cause, "Error injecting {0} using {1}.\r\n  Reason: {2}", type, listener, cause);
        }

        public Errors ErrorNotifyingInjectionListener<I>(InjectionListener<I> listener, Type type, Exception cause)
        {
            return ErrorInUserCode(cause, "Error notifying InjectionListener {0} of {1}.\r\n  Reason: {2}", listener, type, cause);
        }

        public Errors ExposedButNotBound<T>(Key<T> key)
        {
            return AddMessage("Could not expose() {0}, it must be explicitly bound.", key);
        }

        public Errors KeyNotFullySpecified(Type typeLiteral)
        {
            return AddMessage("{0} cannot be used as a key; It is not fully specified.", typeLiteral);
        }

        public Errors ErrorEnhancingClass(Type clazz, Exception cause)
        {
            return ErrorInUserCode(cause, "Unable to method intercept: {0}", clazz);
        }

        public static ICollection<Message> GetMessagesFromThrowable(Exception e)
        {
            if (e is ProvisionException)
            {
                return ((ProvisionException)e).ErrorMessages;
            }
            else if (e is ConfigurationException)
            {
                return ((ConfigurationException)e).ErrorMessages;
            }
            else if (e is CreationException)
            {
                return ((CreationException)e).ErrorMessages;
            }
            else
            {
                return new List<Message>();
            }
        }

        public Errors ErrorInUserCode(Exception cause, string messageFormat, params object[] arguments)
        {
            ICollection<Message> messages = GetMessagesFromThrowable(cause);

            if (messages.Count > 0)
            {
                return Merge(messages);
            }
            else
            {
                return AddMessage(cause, messageFormat, arguments);
            }
        }

        private Exception Unwrap(Exception runtimeException)
        {
            if (runtimeException is NGuiceException)
            {
                return ((NGuiceException)runtimeException).Cause;
            }
            else if (runtimeException.InnerException != null)
            {
                return runtimeException.InnerException;
            }
            else
            {
                return runtimeException;
            }
        }

        public Errors CannotInjectRawProvider()
        {
            return AddMessage("Cannot inject a Provider that has no type parameter");
        }

        public Errors CannotInjectRawMembersInjector()
        {
            return AddMessage("Cannot inject a MembersInjector that has no type parameter");
        }

        public Errors CannotInjectTypeLiteralOf(Type unsupportedType)
        {
            return AddMessage("Cannot inject a TypeLiteral of {0}", unsupportedType);
        }

        public Errors CannotInjectRawTypeLiteral()
        {
            return AddMessage("Cannot inject a TypeLiteral that has no type parameter");
        }

        public Errors CannotSatisfyCircularDependency(Type expectedType)
        {
            return AddMessage("Tried proxying {0} to support a circular dependency, but it is not an interface.", expectedType);
        }

        public Errors CircularProxiesDisabled(Type expectedType)
        {
            return AddMessage("Tried proxying {0} to support a circular dependency, but circular proxies are disabled.", expectedType);
        }

        public void ThrowCreationExceptionIfErrorsExist()
        {
            if (!HasErrors)
            {
                return;
            }
            throw new CreationException(Messages);
        }

        public void ThrowConfigurationExceptionIfErrorsExist()
        {
            if (!HasErrors)
            {
                return;
            }

            throw new ConfigurationException(Messages);
        }

        public void ThrowProvisionExceptionIfErrorsExist()
        {
            if (!HasErrors)
            {
                return;
            }

            throw new ProvisionException(Messages);
        }

        private Message Merge(Message message)
        {
            List<object> sources = Lists.NewArrayList<object>();
            sources.AddRange(Sources);
            //sources.AddRange(message.Sources);
            foreach (var s in message.Sources)
            {
                sources.Add(s);
            }
            return new Message(sources, message.Content, message.Cause);
        }

        public Errors Merge(ICollection<Message> messages)
        {
            foreach (Message message in messages)
            {
                AddMessage(Merge(message));
            }
            return this;
        }

        public Errors Merge(Errors moreErrors)
        {
            if (moreErrors.root == root || moreErrors.root.errors == null)
            {
                return this;
            }
            Merge(moreErrors.root.errors);
            return this;
        }

        public List<object> Sources
        {
            get
            {
                List<object> sources = Lists.NewArrayList<object>();
                for (Errors e = this; e != null; e = e.parent)
                {
                    if (e.source != SourceProvider.UNKNOWN_SOURCE)
                    {
                        sources.Add(e.source);
                        sources.Reverse();
                    }
                }
                return sources;
            }
        }

        public void ThrowIfNewErrors(int expectedSize)
        {
            if (Size == expectedSize)
            {
                return;
            }
            throw ToException();
        }

        public ErrorsException ToException()
        {
            return new ErrorsException(this);
        }

        public bool HasErrors
        {
            get
            {
                return root.errors != null;
            }
        }

        public Errors AddMessage(string messageFormat, params object[] arguments)
        {
            return AddMessage(null, messageFormat, arguments);
        }

        private Errors AddMessage(Exception cause, string messageFormat, params object[] arguments)
        {
            string message = Format(messageFormat, arguments);
            AddMessage(new Message(Sources, message, cause));
            return this;
        }

        public Errors AddMessage(Message message)
        {
            if (root.errors == null)
            {
                root.errors = Lists.NewArrayList<Message>();
            }
            root.errors.Add(message);
            return this;
        }

        public static string Format(string messageFormat, params object[] arguments)
        {
            for (int i = 0; i < arguments.Length; i++)
            {
                arguments[i] = Errors.Convert(arguments[i]);
            }
            return string.Format(messageFormat, arguments);
        }

        public IList<Message> Messages
        {
            get
            {
                if (root.errors == null)
                {
                    return new List<Message>();
                }

                List<Message> result = Lists.NewArrayList<Message>(root.errors);
                result.Sort((a, b) =>
                {
                    //BUG?? c#会出现Cconfigure at offcet #数字 in file:line:column .....
                    //此数字会造成排序错误！TODO:将来版本将使用新的排序规则
                    string aSource = a.Source;
                    string bSource = b.Source;
                    if (a.Source.Contains("in file:"))
                        aSource = a.Source.Substring(a.Source.IndexOf("in file:"));
                    if (b.Source.Contains("in file:"))
                        bSource = b.Source.Substring(b.Source.IndexOf("in file:"));
                    return aSource.CompareTo(bSource);
                });

                return result;
            }

        }

        public static string Format(string heading, ICollection<Message> errorMessages)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(heading).AppendLine().AppendLine();
            int index = 1;
            bool displayCauses = GetOnlyCause(errorMessages) == null;
            IFormatProvider fmt = new DefaultFormatProvider();
            foreach (Message errorMessage in errorMessages)
            {
                sb.AppendFormat("{0}) {1}", index++, errorMessage.Content).AppendLine();
                IList<object> dependencies = (IList<object>)errorMessage.Sources;
                for (int i = dependencies.Count - 1; i >= 0; i--)
                {
                    object source = dependencies[i];
                    FormatSource(fmt, source, ref sb);
                }

                Exception cause = errorMessage.Cause;
                if (displayCauses && cause != null)
                {
                    StringWriter writer = new StringWriter();
                    writer.WriteLine(cause.StackTrace);
                    sb.AppendFormat(fmt, "Caused by: {0}", writer.GetStringBuilder().ToString());
                }
                sb.AppendLine();
            }

            if (errorMessages.Count == 1)
            {
                sb.AppendFormat(fmt, "1 error");
            }
            else
            {
                sb.AppendFormat(fmt, "{0} errors", errorMessages.Count);
            }

            return sb.ToString();
        }

        /// <summary>
        /// 如果没有非null值为null则返回value，否则一个消息被添加到ErrorsException中并被抛出
        /// </summary>
        public T CheckForNull<T>(T value, object source, Dependency dependency)
        {
            if (value != null || dependency.IsNullable)
            {
                return value;
            }
            int parameterIndex = dependency.ParameterIndex;
            string parameterName = (parameterIndex != -1) ? "parameter " + parameterIndex + " of " : "";
            AddMessage("null returned by binding at {0}\r\n but {1}{2} is not [Nullable]", source, parameterName, dependency.InjectionPoint.Member);
            throw ToException();
        }

        /// <summary>
        /// 如果messages中只具有一个错误异常，则返回，如果没有或多个则返回null
        /// </summary>
        public static Exception GetOnlyCause(ICollection<Message> messages)
        {
            Exception onlyCause = null;
            foreach (Message message in messages)
            {
                Exception messageCause = message.Cause;
                if (messageCause == null)
                {
                    continue;
                }

                if (onlyCause != null)
                {
                    return null;
                }

                onlyCause = messageCause;
            }

            return onlyCause;
        }

        public int Size
        {
            get
            {
                return root.errors == null ? 0 : root.errors.Count;
            }
        }

        /// <summary>
        /// C#中不同泛型为不同类型，不能类似java一样使用通配符？表示所有泛型类型。因此，在C#中我们使用dynamic
        /// 关键字来表示通用的类型数据！在方法中将调用动态的方法，此时需要注意传递正确的对象。开发者必须遵守良好
        /// 的开发习惯，如果方法中的参数为dynamic动态类型，应该在注释中明确说明可接受的类型或在方法中处理类型调用异常！
        /// </summary>
        /// <typeparam name="T">要将此对象转换为字符的类型</typeparam>
        internal abstract class Converter<T>
        {

            private Type type;

            public Converter()
            {
                this.type = typeof(T);
            }

            /// <summary>
            /// C#中不同泛型为不同类型，不能类似java一样使用通配符？表示所有泛型类型，因此，如果T是嵌套的泛型类型参数，
            /// 则子类应该根据自己的实际情况重写此应用方法！
            /// </summary>
            public virtual bool AppliesTo(object o)
            {
                return o != null && type.IsAssignableFrom(o.GetType());
            }
            /// <summary>
            /// 这里的参数本应该是T类型，但C#中不同泛型为不同类型，不能类似java一样使用通配符？表示所有泛型类型。
            /// 因此这里参数只能声明为dynamic，不同的子类应该根据自己的实际进行强制转换
            /// </summary>
            public string Convert(object o)
            {
                return ToString(o);
            }

            /// <summary>
            /// 这里的参数本应该是T类型，但C#中不同泛型为不同类型，不能类似java一样使用通配符？表示所有泛型类型。
            /// 因此这里参数只能声明为dynamic，不同的子类应该根据自己的实际进行强制转换
            /// </summary>
            public abstract string ToString(dynamic t);
        }

        internal class ClassConverter : Converter<Type>
        {
            public override string ToString(dynamic o)
            {
                Type c = (Type)o;
                return c.FullName;
            }
        }
        internal class MemberConverter : Converter<MemberInfo>
        {
            public override string ToString(dynamic o)
            {
                MemberInfo member = (MemberInfo)o;
                return Classes.ToString(member);
            }
        }

        internal class KeyConverter : Converter<Key>
        {
            public override bool AppliesTo(object o)
            {
                Type oType = o.GetType();
                while (!oType.IsGenericType && oType.BaseType != typeof(object))
                {
                    oType = oType.BaseType;
                }
                if (oType == typeof(object))
                    return false;
                //这里如果转换类型声明为KeyConverter<object>则任何Key<T>类型都将使用此类型转换器转换
                if (oType.IsGenericType && typeof(Key).IsAssignableFrom(oType))
                {
                    return true;
                }
                return false;
            }

            public override string ToString(dynamic key)
            {
                Key k = (Key)key;
                if (k.AttributeType != null)
                {
                    return k.TypeLiteral + " annotated with " + (k.Attribute != null ? k.Attribute.ToString() : k.AttributeType.ToString());
                }
                else
                {
                    return k.TypeLiteral.ToString();
                }
            }
        }

        public static object Convert(object o)
        {
            foreach (dynamic converter in converters)
            {
                //Type genericType = converter.GetType();
                //if (converter.GetType().IsGenericType) {
                // genericType = converter.GetType().GetGenericTypeDefinition().MakeGenericType(converter.GetType().GetGenericArguments());
                //}  
                //bool applied = (bool)genericType.GetMethod("AppliesTo", new Type[] {typeof(object)}).Invoke(converter, new object[] {o});
                if (converter.AppliesTo(o))
                {
                    //return (string)genericType.GetMethod("Convert", new Type[] {typeof(object)}).Invoke(converter, new object[] {o});
                    return converter.Convert(o);
                }
            }
            return o;
        }

        private static readonly IList converters;

        static Errors()
        {
            converters = new ArrayList();
            converters.Add(new ClassConverter());
            converters.Add(new MemberConverter());
            converters.Add(new KeyConverter());
        }

        public class DefaultFormatProvider : IFormatProvider
        {
            public object GetFormat(Type formatType)
            {
                if (formatType == typeof(DateTime))
                    return CultureInfo.CurrentCulture.DateTimeFormat;
                else if (IsNumber(formatType))
                    return CultureInfo.CurrentCulture.NumberFormat;
                return null;
            }

            private bool IsNumber(Type type)
            {
                if (type == typeof(short)
                    || type == typeof(int)
                    || type == typeof(long)
                    || type == typeof(float)
                    || type == typeof(double)
                    || type == typeof(byte)
                    || type == typeof(decimal))
                    return true;
                return false;
            }
        }

        /// <summary>
        /// 格式化源对象
        /// </summary>
        /// <param name="formatter">格式化提供者</param>
        /// <param name="source">
        /// 由于C#无法提供通配符格式的泛型，因此使用动态参数指定此参数为Dependency<?>或InjectionPoint或Type或MemberInfo或Key<?>实例
        /// </param>
        public static void FormatSource(IFormatProvider formatter, dynamic source, ref StringBuilder builder)
        {
            builder = builder ?? new StringBuilder();
            if (source is Dependency)
            {
                InjectionPoint injectionPoint = source.InjectionPoint;
                if (injectionPoint != null)
                {
                    FormatInjectionPoint(formatter, source, injectionPoint, ref builder);
                }
                else
                {
                    FormatSource(formatter, source.Key, ref builder);
                }
            }
            else if (source is InjectionPoint)
            {
                FormatInjectionPoint(formatter, null, (InjectionPoint)source, ref builder);

            }
            else if (source is Type)
            {
                builder.AppendFormat(formatter, " at {0}", StackFrames.ForType((Type)source));
                builder.AppendLine();
            }
            else if (source is MemberInfo)
            {
                builder.AppendFormat(formatter, " at {0}", StackFrames.ForMember((MemberInfo)source));
                builder.AppendLine();
            }
            else if (source is Key)
            {
                builder.AppendFormat(formatter, "  while locating {0}", Convert(source));
                builder.AppendLine();
            }
            else
            {
                builder.AppendFormat(formatter, " at {0}", source);
                builder.AppendLine();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="dependency">
        /// 由于C#无法提供通配符格式的泛型，因此使用动态参数指定此参数为Dependency实例
        /// </param>
        public static void FormatInjectionPoint(IFormatProvider formatter, dynamic dependency, InjectionPoint injectionPoint, ref StringBuilder builder)
        {
            builder = builder ?? new StringBuilder();//TODO:实现格式化注入点的方法！
            MemberInfo member = injectionPoint.Member;
            Type memberType = Classes.MemberType(member);

            if (memberType == typeof(FieldInfo))
            {
                dependency = injectionPoint.Dependencies[0];
                builder.AppendFormat(formatter, "  while locating {0}", Convert(dependency.Key));
                builder.AppendLine();
                builder.AppendFormat("    for field at {0}", StackFrames.ForMember(member));
                builder.AppendLine();
            }
            else if (dependency != null)
            {
                builder.AppendFormat("  while locating {0}", Convert(dependency.Key));
                builder.AppendLine();
                builder.AppendFormat("    for parameter {0} at {1}", dependency.ParameterIndex, StackFrames.ForMember(member));
                builder.AppendLine();
            }
            else
            {
                FormatSource(formatter, injectionPoint.Member, ref builder);
            }
        }
    }
}
